using UnityEngine;
using YooAsset;
using System.Reflection;
using System.Linq;

namespace shaco
{
    internal abstract class DCFExtensionsOperation : GameAsyncOperation
    {
        internal protected ResourcePackage _package;
        internal protected EPlayMode _playMode = EPlayMode.EditorSimulateMode;

        protected override void OnStart()
        {
            var filed = _package.GetType().GetField("_playMode", BindingFlags.Instance | BindingFlags.NonPublic);
            _playMode = (EPlayMode)filed.GetValue(_package);
        }

        protected override void OnAbort()
        {
            
        }

        public void SetPackage(ResourcePackage package)
        {
            this._package = package;

        }
    }

    internal class DCFSClearUnusedManifestFilesOperation : DCFExtensionsOperation
    {
        protected override void OnUpdate()
        {
            //只有在线模式需要清理本地下载过的多余的manifest文件
            if (_playMode != EPlayMode.HostPlayMode)
            {
                Status = EOperationStatus.Succeed;
                return;
            }

            var cacheRootPath = YooAsssetPackageExtensions.GetManifestRootPath(_package);
            var files = System.IO.Directory.GetFiles(cacheRootPath, "*.*").Where(v => System.IO.Path.GetFileName(v).Contains(_package.PackageName));

            if (0 == files.Count())
            {
                Debug.LogError("DCFSClearUnusedManifestFilesOperation error: not found manifest file in path=" + cacheRootPath);
            }

            foreach (var iter in files)
            {
                //非当前版本manifest都删除掉
                if (!iter.Contains(_package.GetPackageVersion()))
                {
                    try
                    {
                        System.IO.File.Delete(iter);
                        Status = EOperationStatus.Succeed;
                    }
                    catch (System.Exception ex)
                    {
                        Debug.LogError("DCFSClearUnusedManifestFilesOperation error: path=" + iter + ", error=" + ex);
                    }
                    Debug.Log("Delete unused manifest file path=" + iter);
                }
            }
            Status = EOperationStatus.Succeed;
        }
    }

    static public class YooAsssetPackageExtensions
    {
        static public AsyncOperationBase ClearUnusedManifestFilesAsync(this ResourcePackage package)
        {
            var operation = new DCFSClearUnusedManifestFilesOperation();
            operation.SetPackage(package);
            YooAssets.StartOperation(operation);
            return operation;
        }

        static public string GetLastNewPackageVersion(this ResourcePackage package)
        {
            var cacheRootPath = YooAsssetPackageExtensions.GetManifestRootPath(package);
            var allFiles = System.IO.Directory.GetFiles(cacheRootPath, "*.*");
            var files = allFiles.Where(v => System.IO.Path.GetFileName(v).Contains(package.PackageName));
            var fileCount = files.Count();
            if (0 == fileCount)
            {
                Debug.LogError("没有在本地找到manifest文件, 根目录=" + cacheRootPath);

                var strTmp = new System.Text.StringBuilder($"当前目录文件{allFiles.Count()}\n");
                foreach (var iter in allFiles)
                {
                    strTmp.Append(iter);
                    strTmp.Append('\n');
                }
                Debug.Log(strTmp.ToString());
                return string.Empty;
            }


            if (fileCount > 0)
                files = OrderByAlphaNumeric(files, v => v);
            var lastManifestFilePath = System.IO.Path.GetFileNameWithoutExtension(files.Last());
            var checkStr = $"{package.PackageName}_";
            var retValue = lastManifestFilePath.Substring(checkStr.Length);
            return retValue;
        }

        static internal System.Linq.IOrderedEnumerable<T> OrderByAlphaNumeric<T>(System.Collections.Generic.IEnumerable<T> source, System.Func<T, string> selector)
        {
            int max = source.SelectMany(i => System.Text.RegularExpressions.Regex.Matches(selector(i), @"\d+").Cast<System.Text.RegularExpressions.Match>().Select(m => (int?)m.Value.Length))
                            .Max() ?? 0;
            return source.OrderBy(i => System.Text.RegularExpressions.Regex.Replace(selector(i), @"\d+", m => m.Value.PadLeft(max, '0')));
        }

        //该方法参考自 YooAsset.DefaultCacheFileSystem.GetDefaultRoot()
        static internal string GetDefaultRoot()
        {
#if UNITY_EDITOR
            // 注意：为了方便调试查看，编辑器下把存储目录放到项目里。
            string projectPath = System.IO.Path.GetDirectoryName(UnityEngine.Application.dataPath);
            projectPath = projectPath.Replace('\\', '/').Replace("\\", "/");
            return $"{projectPath}/yoo";
#elif UNITY_STANDALONE
            return $"{UnityEngine.Application.dataPath}/yoo";
#else
            return $"{UnityEngine.Application.persistentDataPath}/yoo";
#endif
        }

        static internal string GetManifestRootPath(ResourcePackage package)
        {
            var cacheRootPath = $"{YooAsssetPackageExtensions.GetDefaultRoot()}/{package.PackageName}/ManifestFiles";
            return cacheRootPath;
        }
    }
}